﻿using Nemerle;
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;

namespace Ammy.Infrastructure
{
  public module ReflectionTypeProvider
  {
    private _typesByFullName : ConcurrentDictionary[string, Type] = ConcurrentDictionary();
    private _locker = object();
    
    public FindType(typeName : string) : Type
    {      
        lock (_locker) {
          when (_typesByFullName.Count == 0) {
              def allTypes = AppDomain.CurrentDomain
                                      .GetAssemblies()
                                      .SelectMany(a => try { a.GetTypes() } catch { _=> [] })
                                      .Concat(Assembly.GetExecutingAssembly()
                                                      .GetTypes());

              foreach (type in allTypes)
                  _ = _typesByFullName.TryAdd(type.FullName, type);
          }
        }

        mutable ret;
        if (_typesByFullName.TryGetValue(typeName, out ret)) ret;
        else throw InvalidOperationException("Couldn't find type: " + typeName);
    }
  }
}
